﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Windows.Controls;
using Trinity.Components.Combat;
using Trinity.Components.Combat.Resources;
using Trinity.Framework;
using Trinity.Framework.Actors.ActorTypes;
using Trinity.Framework.Avoidance.Structures;
using Trinity.Framework.Helpers;
using Trinity.Framework.Objects;
using Trinity.Framework.Reference;
using Trinity.Settings;
using Trinity.UI;
using Zeta.Common;
using Zeta.Game.Internals.Actors;


namespace Trinity.Routines.Necromancer
{
    public sealed class NecromancerRathmaMages : NecroMancerBase, IRoutine
    {
        #region Definition


        public string DisplayName => "骨套召唤1.6.2";
        public string Description => "1.6.2更新内容：减少贴脸情况" + System.Environment.NewLine +
            "固定技能 : 骷髅法师-精魂灌注，吞噬-嗜血灵气，衰老-眩晕诅咒，号令骸骨-黑暗愈合。" + System.Environment.NewLine  +
            "被动 : 求死不能，精魄魂身，亡者滋养，绝命效忠。" + System.Environment.NewLine  +
            "大米 : 骨刺-出其不意，血魂双分-血盈血魂。" + System.Environment.NewLine  + 
            "小米 : 鲜血虹吸-鲜血饥渴，鲜血奔行-鲜血潜能。   装备技能搭配点击下面链接查看";
        public string Author => "Beastfxx";
        public string Version => "1.6.2";
        public string Url => "https://www.d3planner.com/193564756";
        public Build BuildRequirements => null;
        public const int P6_NECRO_SKELETONMAGE_C = 472606;
     
       #endregion

        #region IRoutine Defaults




        #endregion

        private const float CombatRange = 30f;
        private const float CloseToRangeMin = 15f;
        private const float CloseToRangeMax = 20f;


        public TrinityPower GetOffensivePower()
        {
            TrinityPower power;
            TrinityActor target;
               
    
            if (TryBloodPower(out power))
                return power;

            if (TryReanimationPower(out power))
                return power;

            if (TryCursePower(out power))
                return power;

            if (TrySecondaryPower(out power))
                return power;
            
            if (TryPrimaryPower(out power))
                return power;
        

            return null;
        }

        #region Helpers and Conditions




protected override bool ShouldSkeletalMage(out Vector3 position)
        {
            position = Vector3.Zero;
            SummonInfo summons = GetPlayerSummonCounts();
			

            if (!Skills.Necromancer.SkeletalMage.CanCast())
                return false;


            if (Player.PrimaryResourcePct < CastMagesPct)
                return false;

            if (summons.SkeletonMageCount == 10)
                return false;



            position = TargetUtil.GetBestClusterPoint();
            return position != Vector3.Zero;
        }


        protected override bool ShouldDevour()
        {
            if (!Skills.Necromancer.Devour.CanCast())
                return false;

            if (Player.PrimaryResourcePct > 0.7f)
                return false;

            if (TargetUtil.CorpseCount(60f) <= 0)
                return false;

            return true;
        }

        protected override bool ShouldBoneSpikes(out TrinityActor target)
     {
            target = null;

            if (!Skills.Necromancer.BoneSpikes.CanCast())
                return false;
 
   //   target = TargetUtil.GetBestClusterUnit() ?? CurrentTarget;
            target = TargetUtil.BestEliteInRange(15f) ?? TargetUtil.GetBestClusterUnit() ?? TargetUtil.ClosestUnit(10f) ?? CurrentTarget;

      
            return target != null;
   
        }

        protected override bool ShouldDecrepify(out TrinityActor target)
        {
            target = null;
            if (!Skills.Necromancer.Decrepify.CanCast())
                return false;

            if (Player.PrimaryResource < PrimaryEnergyReserve)
                return false;

            // todo: investigate why cant find the power on monsters.         

            // anti-spam workaround
            if (Skills.Necromancer.Decrepify.TimeSinceUse < 4500)
                return false;

            target = TargetUtil.BestTargetWithoutDebuff(30f, SNOPower.P6_Necro_Decrepify);

            return target != null;
        }

        private bool IsPathClearForBloodRush(Vector3 destination)
        {

            if (!Skills.Necromancer.BloodRush.IsActive)
                return false;

            return true;
        }

        private bool ShouldOffensiveBloodRush(Vector3 position)
        {
            return (Player.CurrentHealthPct > Settings.EmergencyHealthPct) && Skills.Necromancer.BloodRush.CanCast() && position.Distance(Player.Position) > 15;
        }

        private bool ShouldEvasiveBloodRush()
        {
            return Skills.Necromancer.BloodRush.CanCast() && ((!Core.Buffs.HasInvulnerableShrine && Core.Avoidance.InAvoidance(Player.Position)) && Player.CurrentHealthPct < Settings.EmergencyHealthPct);
        }

        protected override bool ShouldSimulacrum(out Vector3 position)
        { 
            position = Vector3.Zero;
            if (!Skills.Necromancer.Simulacrum.CanCast())
                return false;

            if (!TargetUtil.AnyElitesInRange(30f))
                return false;

            return true;
        }





        protected bool TryReanimationPower(out TrinityPower power)
        {
            TrinityActor target;
            Vector3 position;
            power = null;

            if (ShouldCommandSkeletons(out target) && Skills.Necromancer.CommandSkeletons.TimeSinceUse > 7000)
                power = CommandSkeletons(target);

            return power != null;
        }

        private class SummonInfo
        {
            public int SkeletonMageCount = 0;
        }

        private SummonInfo GetPlayerSummonCounts()
        {
            var info = new SummonInfo();

            foreach (var actor in Core.Actors.Actors)
            {
                if (!actor.IsSummonedByPlayer)
                    continue;

                var actorSnoId = actor.ActorSnoId;


                if (GameData.AncientIds.Contains(P6_NECRO_SKELETONMAGE_C))
                    info.SkeletonMageCount++;

            }

            return info;
        }

        #endregion

        private bool ShouldApplyCurseWithScythe()
        {
            // Inarius build with Shadowhook should rarely run out of resource to force primary,
            // so it needs to be occasionally prioritized to apply curses.
            return Runes.Necromancer.CursedScythe.IsActive && Skills.Necromancer.GrimScythe.TimeSinceUse > 2000;
        }

        protected override bool ShouldCommandSkeletons(out TrinityActor target)
        {
            if (base.ShouldCommandSkeletons(out target))
            {
                return Skills.Necromancer.CommandSkeletons.TimeSinceUse > 5000;
            }
            return false;
        }

        public TrinityPower GetDefensivePower()
        {
            return GetBuffPower();
        }

        public TrinityPower GetBuffPower()
        {
            if (Player.CurrentHealthPct < 0.25 && Skills.Necromancer.BloodRush.CanCast())
            {
                return BloodRush(Avoider.SafeSpot);
            }
            // Put up bone armor when running around with high cluster size setting and not yet fighting
            if (!Skills.Necromancer.BoneArmor.IsBuffActive && TargetUtil.AnyMobsInRange(15f, 3))
            {
                return BoneArmor();
            }

           if (ShouldDevour())
                return Devour();

            return null;
        }

        private bool ShouldLandOfTheDead(TrinityActor target)
        {
            if (target == null)
                return false;

            if (!Skills.Necromancer.LandOfTheDead.CanCast())
                return false;

            if (IsTargetSpecial(target))
            {
                return true;
            }

            return false;
        }

protected bool TryCorpsePower(out TrinityPower power)
        {
            TrinityActor target;
            Vector3 position;
            power = null;


          if (ShouldDevour())
                power = Devour();

            return power != null;
        }

        private bool IsTargetSpecial(TrinityActor target)
        {
            if (target == null)
                return false;

            return target.IsElite || target.IsBoss || target.IsRare || target.IsTreasureGoblin;
        }

        public TrinityPower GetDestructiblePower()
        {
            return DefaultDestructiblePower();
        }

        public TrinityPower GetMovementPower(Vector3 destination)
        {
            TrinityPower power;

            if (!IsInCombat || CurrentTarget != null && CurrentTarget.IsElite && CurrentTarget.Position.Distance(destination) <= 10f)
            {
                if (TryBloodrushMovement(destination, out power))
                    return power;
            }

            if (!TargetUtil.AnyMobsInRange(CloseToRangeMin) || Core.Avoidance.InAvoidance(Player.Position) || Player.IsGhosted)
                return Walk(destination);
            return GetOffensivePower();
           
              if (IsStuck || IsBlocked)//TargetUtil.NumMobsInRange(15f)>6)
            {
                var target = TargetUtil.GetClosestUnit(10f);
                if (target != null)
               return GetOffensivePower();
            }
            return Walk(destination,10f);
        }

        #region Settings      

        public override int ClusterSize => Settings.ClusterSize;
        public override float EmergencyHealthPct => Settings.EmergencyHealthPct;
        public float CastMagesPct => Settings.CastMagesPct;

        IDynamicSetting IRoutine.RoutineSettings => Settings;
        public NecromancerRathmaMagesSettings Settings { get; } = new NecromancerRathmaMagesSettings();

        public sealed class NecromancerRathmaMagesSettings : NotifyBase, IDynamicSetting
        {
            private int _clusterSize;
            private float _emergencyHealthPct;
            private float _castMagesPct;

            [DefaultValue(1)]
            public int ClusterSize
            {
                get { return _clusterSize; }
                set { SetField(ref _clusterSize, value); }
            }

            [DefaultValue(0.4f)]
            public float EmergencyHealthPct
            {
                get { return _emergencyHealthPct; }
                set { SetField(ref _emergencyHealthPct, value); }
            }

            [DefaultValue(0.4f)]
            public float CastMagesPct
            {
                get { return _castMagesPct; }
                set { SetField(ref _castMagesPct, value); }
            }

            public override void LoadDefaults()
            {
                base.LoadDefaults();
                //WrathOfTheBerserker = WrathOfTheBerserkerDefaults.Clone();
                //FuriousCharge = FuriousChargeDefaults.Clone();
            }

            #region IDynamicSetting

            public string GetName() => GetType().Name;
            public UserControl GetControl() => UILoader.LoadXamlByFileName<UserControl>(GetName() + ".xaml");
            public object GetDataContext() => this;
            public string GetCode() => JsonSerializer.Serialize(this);
            public void ApplyCode(string code) => JsonSerializer.Deserialize(code, this, true);
            public void Reset() => LoadDefaults();
            public void Save() { }

            #endregion
        }

        #endregion
    }
}


